package com.candy.candylogservice.config;

import com.alibaba.fastjson2.JSONB;
import com.alibaba.fastjson2.JSONObject;
import com.candy.candycommon.utils.ApplicationContentUtils;
import com.candy.candycommon.utils.AxinDispatcherServlet;
import com.candy.candylogservice.dto.LogLinkDTO;
import com.candy.candylogservice.interceptor.LogInterceptor;
import com.candy.candylogservice.interceptor.LogUtils;
import com.candy.candylogservice.queue.LogQueue;
import com.candy.candylogservice.service.LogLinkService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * @author suYanLong
 * @date 2022年10月25日 14:51
 */
@Configuration
@ConditionalOnProperty(prefix = "rpc", name = "log.enable", havingValue = "true", matchIfMissing = true)
public class LogLinkConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //多个拦截器会按照顺序进行校验拦截  内部维护了一个list集合 registrations
        registry.addInterceptor(new LogInterceptor());
    }

    @Bean
    @Qualifier(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
    public DispatcherServlet dispatcherServlet() {
        return new AxinDispatcherServlet();
    }

    @ControllerAdvice
    class LogResponseAdvice implements ResponseBodyAdvice {

        @Override
        public boolean supports(MethodParameter methodParameter, Class aClass) {
            return true;
        }

        @Override
        public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {

            LogLinkDTO logLinkDTO = LogUtils.getLog();
            if (logLinkDTO != null && logLinkDTO.getId() != null) {
                // log.error("打印返回参数：{}", logLinkDTO);
                logLinkDTO.setResponseData(JSONObject.toJSONString(o));
                LogLinkService logLinkService = ApplicationContentUtils.getBean(LogLinkService.class);
                ThreadPoolTaskExecutor executor = (ThreadPoolTaskExecutor) ApplicationContentUtils.getApplicationContext().getBean("asyncTaskExecutor");
                executor.execute(() -> {
                    try {
                        logLinkService.save(logLinkDTO);
                    } catch (Exception e) {
                        LogQueue.logLinkQueue.add(logLinkDTO);
                    }
                });
                LogUtils.clear();
            }
            return o;
        }

    }

}
